package com.qianfeng.springsecuriry.config;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.qianfeng.springsecuriry.handler.LoginSuccessHandler;
import com.qianfeng.springsecuriry.mapper.MenuMapper;
import com.qianfeng.springsecuriry.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * Created by Jackiechan on 2022/8/18 20:44
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@EnableWebSecurity
//开启注解权限
@EnableGlobalMethodSecurity(prePostEnabled = true,proxyTargetClass = true,jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    private MenuMapper menuMapper;

    @Autowired
    public void setMenuMapper(MenuMapper menuMapper) {
        this.menuMapper = menuMapper;
    }


    private BCryptPasswordEncoder bCryptPasswordEncoder;
    //设置密码的编码方式
    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    private MyUserDetailService myUserDetailService;


    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    public void setLoginSuccessHandler(LoginSuccessHandler loginSuccessHandler) {
        this.loginSuccessHandler = loginSuccessHandler;
    }

    @Autowired
    public void setMyUserDetailService(MyUserDetailService myUserDetailService) {
        this.myUserDetailService = myUserDetailService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       //在这里我们可以配置告诉security如何判断自己定义的账号和密码
        //当我们登录的时候在登录页面输入了自己的账号和密码,spring security会执行我们自己定的判断方式,
        //会告诉我们输入的账号是什么,然后要求我们返回这个账号在数据库中的密码,然后security会比较传递进来的密码和数据库中的密码是不是一样的
        //一样的就认为登录成功
        //设置查询用户的方式以及数据库中的密码是用什么进行编码的
        auth.userDetailsService(myUserDetailService).passwordEncoder(bCryptPasswordEncoder);
    }





    @Override
    public void configure(WebSecurity web) throws Exception {
        //我们有些地址是不拦截的,比如我们的静态资源文件
        web.ignoring().antMatchers("/js/**", "/test/test1", "/css/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();//禁用防跨域
        //我们在这里可以配置项目中每个地址需要什么权限
//        List<SysMenu> allMenus = menuMapper.findAllMenus();
//        allMenus.forEach(sysMenu -> {
//            if (StringUtils.hasText(sysMenu.getUrl()) && StringUtils.hasText(sysMenu.getPerms())) {
//
//                try {
//                    //给我们指定的地址设置指定的权限
//                    http.authorizeRequests().antMatchers(sysMenu.getUrl()).hasAuthority(sysMenu.getPerms());
//                } catch (Exception e) {
//                    throw new RuntimeException(e);
//                }
//            }
//
//        });


        //可以配置我们的一些登录的配置
        http.authorizeRequests()//对我们的请求进行认证的设置
                .and().formLogin()//自定义登录
                //.loginPage()//自定义我们自己的登录页面,不设置会使用spring security默认的
                .loginProcessingUrl("/login")//自定义登录的处理地址,默认就是/login 在设置了自定义loginPage的情况下,我们自己定义登录页面中form表单的地址需要和这个保持一致,这个地址我们不需要编写,并且不能编写
                // .usernameParameter()//自定义我们传递的参数中用户名的参数是什么/默认是username,如果写了自定义的页面,自定义页面中用户名所在的参数必须和这个名字一样
                //  .passwordParameter()//自定义我们传递的参数中密码的参数是什么/默认是password,如果写了自定义的页面,自定义页面中密码所在的参数必须和这个名字一样
                //.successForwardUrl()//自定义登录成功后跳转到什么地址
                .successHandler(loginSuccessHandler)//自定义登录成功后干什么
             //   .failureHandler()//自定义登录失败后干什么
                .permitAll()//登录地址是不需要验证登录的,而是直接放行
                .and().logout()//设置退出的操作
                .logoutUrl("/logout")//自定义退出的地址,默认就是logout,这个地址自定义后不允许自己编写
               // .logoutSuccessUrl()//自定义退出成功后跳转到什么地址
               // .logoutSuccessHandler()//自定义退出成功后干什么
                .and().authorizeRequests().anyRequest().authenticated();//除了上面自定义的地址外都需要认证

    }
}
